4.6 接口

接口一般来说在开发一些工具库、框架时比较有用,与Java等语言不同但是也有类似的地方。

同时接口我们也会用在一些未知类型的判断上面,当我们不知道类型具体是什么时,我们也会使用接口来实现。

在学习本章节前,可以先去学习第五章,之后再来学习这一章会更好

本节代码存放目录为 lesson11

什么是接口

接口在Go语言中也就是interface,是一种特殊的数据类型。

我们需要记住的是,接口可以用来表示任意类型,同时接口可以用来定义一组方法合集,之后由结构体去实现。

在之前的章节中,我们学习了变量的声明及定义,如下所示:

var varName varType;
var a int;

那么有了接口之后,我们可以这样定义:

var a interface{}

如上代码所示,就表示a可以是任意的一种类型,可以是intstringfloat32等任一种类型。

在上一节中我们学习了结构体,但是我们没有讲解结构方法,我们将在这一章节中一起讲解。

作为变量类型使用

在上面我们已经输出了定义方式,现在我们来开始测试,如下所示:

var a interface{}
a = 8;
fmt.Println(a)

输出结果如下:

8

在上面的代码中,我们将a变量的类型定义为interface{},之后我们为a变量赋值为8,执行代码后没有报错,结果输出了8

这样就是一个interface的简单应用,也就是当我们对于变量的类型未知时,我们可以使用interface来进行处理。

结构体方法

结构体方法与其他语言类似,当我们定义了一个结构体时,他不仅拥有变量,同时也可以拥有属于他的方法。如下代码所示:

type Dog struct {
    Voice string
}

func (d Dog) Speak() {
    fmt.Println(d.Voice)
}

dog := Dog{
    Voice: "Wang...",
}
dog.Speak()

在上面的代码中,我们定义了一个结构体Dog,其中包含一个字段Voice

在之后,我们又写了一个方法,方法的作用是将结构体的Voice字段打印出来:

func (d Dog) Speak() {
    fmt.Println(d.Voice)
}

上面的代码就演示了结构体方法是如何使用的。

在前面我们讲到,结构体可以通过符号:.来引用结构体的字段,那么同样的,方法也是一样的来处理。

当我们声明结构体变量后,为Voice赋值,之后通过结构体变量dog直接调用:dog.Speak()即可。

结果输出如下:

Wang!

接口及结构体方法使用

上面我们讲到了结构体方法的使用,那么如果我们有很多的结构体都有相同的方法应该怎么处理呢?

比如说我们有很多个小动物的结构体,同时都需要调用结构体的Speak

这时候再像上面的一样去处理也是可以实现的,但是代码复杂度就会增高。

那么这里就涉及到了接口的多态性,如下代码所示:

type Animal interface {
    Speak()
}

type Dog struct {
    Voice string
}

func (d Dog) Speak() {
    fmt.Println(d.Voice)
}

type Cat struct {
    Voice string
}

func (c Cat) Speak() {
    fmt.Println(c.Voice)
}

var animalDog Animal = Dog{
    Voice: "Wang...",
}
animalDog.Speak()

var animalCat Animal = Cat{
    Voice: "Miao...",
}
animalCat.Speak()

如上代码所示,首先我们定义了Animal的接口,接口里面有一个方法:Speak

另外我们定义了DogCat两个结构体,两个结构体都实现了Speak方法。

由于Animal是一个interface,而interface又具有任意类型的特性。

所以我们可以直接声明:var animalDog Animal = Dog{}、以及var animalCat Animal = Cat{}

这样我们就可以很容易的调用:animalDog.Speak()animalCat.Speak()来进行对应的输出。

那么看到这里可能会有个疑问,为什么要这么做呢?直接使用dog.Speakcat.Speak同样可以实现相同效果,为什么反而要使用interface来进行更复杂的操作呢?

我们直接看下面的代码:

func animalSpeak(animal Animal) {
    animal.Speak()
}

var animalDog1 Animal = Dog{
    Voice: "Wang...",
}
animalSpeak(animalDog1)

var animalCat1 Animal = Cat{
    Voice: "Miao...",
}
animalSpeak(animalCat1)

在上面的代码中,我们首先定义了一个函数:animalSpeak,函数接收Animal类型的参数。

之后我们同样声明了:animalDog1animalSpeak,之后将这两个变量作为参数传递给了animalSpeak

结果输出如下:

Wang...
Miao...

从上面的代码我们可以看出,使用interface以及结构体方法来配合的方式,就是为了可以让代码更加通用、扩展。

在这里我们举例比较简单,所以看不出太大的区别,但是如果在实际工程中,这样的场景运用就会特别多。

比如我们现在需要新增几种小动物,那么我们就不需要再去修改现在的代码,而是新增结构体实现了Speak即可。

小结

Go语言接口interface在实际应用中比较广泛,主要在实际的工程项目中使用的比较多。

比如开发API接口、请求第三方API获取数据等,都会经常用到这个特殊类型。

经过本节学习,总结如下:

  • 接口可以是任意类型的

  • 接口常与结构体方法来配合使用

  • 结构体方法必须实现接口所定义的所有方法

  • 可以参照Java的接口来理解,但是稍微有一点不同

results matching ""

    No results matching ""